Use a stamp file to protect against corrupt checkouts
authorAlex Crichton <alex@alexcrichton.com>
Wed, 9 Sep 2015 22:44:43 +0000 (15:44 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 9 Sep 2015 23:23:43 +0000 (16:23 -0700)
We already take this strategy for extracting tarballs from crates.io for
example, so this just applies the same strategy to checkouts of git repos.

Closes #1979

src/cargo/sources/git/utils.rs
tests/test_cargo_compile.rs

index 51f69a6d27e893be49146dcba1421bee55a949f3..f51b9dc97b9f0bf3f6749ad89cb4a046c78b0d88 100644 (file)
@@ -1,6 +1,6 @@
 use std::fmt;
 use std::path::{Path, PathBuf};
-use std::fs;
+use std::fs::{self, File};
 
 use rustc_serialize::{Encodable, Encoder};
 use url::Url;
@@ -267,7 +267,10 @@ impl<'a> GitCheckout<'a> {
 
     fn is_fresh(&self) -> bool {
         match self.repo.revparse_single("HEAD") {
-            Ok(head) => head.id().to_string() == self.revision.to_string(),
+            Ok(ref head) if head.id() == self.revision.0 => {
+                // See comments in reset() for why we check this
+                fs::metadata(self.location.join(".cargo-ok")).is_ok()
+            }
             _ => false,
         }
     }
@@ -282,9 +285,20 @@ impl<'a> GitCheckout<'a> {
     }
 
     fn reset(&self) -> CargoResult<()> {
+        // If we're interrupted while performing this reset (e.g. we die because
+        // of a signal) Cargo needs to be sure to try to check out this repo
+        // again on the next go-round.
+        //
+        // To enable this we have a dummy file in our checkout, .cargo-ok, which
+        // if present means that the repo has been successfully reset and is
+        // ready to go. Hence if we start to do a reset, we make sure this file
+        // *doesn't* exist, and then once we're done we create the file.
+        let ok_file = self.location.join(".cargo-ok");
+        let _ = fs::remove_file(&ok_file);
         info!("reset {} to {}", self.repo.path().display(), self.revision);
         let object = try!(self.repo.find_object(self.revision.0, None));
         try!(self.repo.reset(&object, git2::ResetType::Hard, None));
+        try!(File::create(ok_file));
         Ok(())
     }
 
index 62dfd76f2c2327bbe99c400c208c7b2f3dd7c145..482a6dee442516ad2c82db3bf0a2fa5436626568 100644 (file)
@@ -1508,7 +1508,7 @@ test!(cargo_platform_specific_dependency {
                 execs().with_status(0));
 
     assert_that(&p.bin("foo"), existing_file());
-    assert_that(p.cargo_process("test"),
+    assert_that(p.cargo("test"),
                 execs().with_status(0));
 });